#pragma once
#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>
#include <string>
#include <map>
#include <ctime>
#include <unistd.h>
#include <cstdarg>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "LockGuard.hpp"

const static std::string SEP = "|";
const static std::string LOGPAGE_SIGN = "LOGINPAGE";
const static std::string CHAT_SIGN = "CHAT";

const static std::string MSG_SIGN = "MSG";
const static std::string LOG_SIGN = "LOGIN";
const static std::string REG_SIGN = "REG";
const static std::string HIS_SIGN = "HIS";
const static std::string QUIT_SIGN = "QUIT";

const static std::string LOG_SUCCESS = LOGPAGE_SIGN+SEP+"LOG_SUCCESS";
const static std::string LOG_FAIL =  LOGPAGE_SIGN+SEP+"LOG_FAIL";
const static std::string REG_SUCCESS =  LOGPAGE_SIGN+SEP+"REG_SUCCESS";
const static std::string REG_FAIL = LOGPAGE_SIGN+SEP+"REG_FAIL";
const static std::string REG_OCPIED =  LOGPAGE_SIGN+SEP+"REG_OCCUPIED";

enum MessageType {
    TEXT_TYPE, // ⽂本消息
    IMAGE_TYPE, // 图⽚消息
    FILE_TYPE, // ⽂件消息
    SPEECH_TYPE, // 语⾳消息
    UNKNOWN_TYPE, // 错误类型
    HISTORY_TYPE
};

enum
{
    SOCKET_ERROR = 1,
    BIND_ERROR,
    USAGE_ERROR,
    CONNECTSQL_ERROR
};

int openDev(const std::string &dev, int flag)
{
    int fd = open(dev.c_str(), flag);
    if (fd < 0)
    {
        std::cerr << "open error" << std::endl;
        return -1;
    }
    return fd;
}
void Setserver(struct sockaddr_in &server, std::string &serverip, uint16_t &serverport)
{
    bzero(&server, sizeof(server));
    server.sin_port = htons(serverport);
    server.sin_addr.s_addr = inet_addr(serverip.c_str());
    server.sin_family = AF_INET;
}

class InetAddr
{
    void GetAddress(uint16_t *Port, std::string *Ip)
    {
        *Port = ntohs(_Addr.sin_port);
        *Ip = inet_ntoa(_Addr.sin_addr);
    }

public:
    InetAddr(struct sockaddr_in &Addr)
        : _Addr(Addr)
    {
        GetAddress(&_Port, &_Ip);
    }
    bool operator==(const InetAddr &addr) const
    {
        return _Ip == addr._Ip && _Port == addr._Port;
    }

    bool operator<(const InetAddr &other) const
    {
        return std::tie(_Ip, _Port) < std::tie(other._Ip, other._Port);
    }

    uint16_t Port() const
    {
        return _Port;
    }

    std::string Ip() const
    {
        return _Ip;
    }

    struct sockaddr_in Addr() const
    {
        return _Addr;
    }

private:
    struct sockaddr_in _Addr;
    uint16_t _Port;
    std::string _Ip;
};
